cesium教程(三):Entity API

您所在的位置:网站首页 cesium point cesium教程(三):Entity API

cesium教程(三):Entity API

#cesium教程(三):Entity API| 来源: 网络整理| 查看: 265

Entity

Entity API 的主要目的是定义一组高级对象,它们把可视化和信息存储到统一的数据结果中,这个对象叫 Entity。 它让我们更加关注我们的数据展示而不是底层的可视化机制。它提供了很方便的创建复杂的与静态数据相匹配的随时间变化的可视化效果。Entity内部也是使用了 Primitive ,它的实现细节,我们无需关心,Entity暴露一些一致性的、容易去学习和使用的接口。

通常使用 viewer.entities.add 方法进行添加Entity矢量数据,或者使用 CustomDataSource 对象进行管理。

属性描述id唯一标志,如果没设置,值就为一个默认给定的GUIDname名称,可以不唯一availability可用性show可见性description描述position位置orientation方向viewFrom查看此对象的初始偏移量parent父节点properties与此实体关联的任意属性 几何种类 类型线框模式point点label标签billboard广告牌polyline折线polylineVolume管线corridor走廊wall墙plane平面polygon多边形box盒子rectangle矩形cylinder圆柱ellipse椭圆ellipsoid椭球model模型tileset3D Tilespath路径

image.png

点和标签

通过设置 position 和 point 来创建图形点或标签label。

var viewer = new Cesium.Viewer('cesiumContainer'); var citizensBankPark = viewer.entities.add({ name : 'Citizens Bank Park', position : Cesium.Cartesian3.fromDegrees(-75.166493, 39.9060534), point : { pixelSize: 5, color: Cesium.Color.RED, outlineColor: Cesium.Color.WHITE, outlineWidth: 2 }, label : { text: 'Citizens Bank Park', font: '14pt monospace', style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 2, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -9) } }); viewer.zoomTo(viewer.entities); 复制代码

image.png

默认情况下,标签水平和垂直居中。由于标签和点共享相同的位置,它们在屏幕上重叠。为避免这种情况,请指定标签原点 VerticalOrigin.BOTTOM 并将像素偏移设置为 (0, -9)。

广告牌

用 billboard 替换点 ,这是一个始终面向用户的标记。

var citizensBankPark = viewer.entities.add({ position : Cesium.Cartesian3.fromDegrees(-75.166493, 39.9060534), billboard : { image : '/docs/images/tutorials/creating-entities/Philadelphia_Phillies.png', width : 64, height : 64 }, label : { text : 'Citizens Bank Park', font : '14pt monospace', style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 填充样式:重新填写并标记文本 outlineWidth : 2, verticalOrigin : Cesium.VerticalOrigin.TOP, // 垂直原点 pixelOffset : new Cesium.Cartesian2(0, 32) // 偏移 } }); 复制代码

image.png

模型

CesiumJS 通过glTF 格式支持 3D 模型 。

为 glTF 模型设置位置和 URI 以创建模型实体。

var viewer = new Cesium.Viewer('cesiumContainer'); var entity = viewer.entities.add({ position : Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706), model : { uri : '../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb' } }); viewer.trackedEntity = entity; // 追踪 复制代码

image.png

默认情况下,模型是直立面向东的。通过Quaternion 为Entity.orientation属性指定模型的航向、俯仰和滚动。

var viewer = new Cesium.Viewer('cesiumContainer'); var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706); var heading = Cesium.Math.toRadians(45.0); var pitch = Cesium.Math.toRadians(15.0); var roll = Cesium.Math.toRadians(0.0); var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(heading, pitch, roll)); var entity = viewer.entities.add({ position : position, orientation : orientation, model : { uri : '../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb' } }); viewer.trackedEntity = entity; 复制代码 材质和轮廓

所有形状和体积都有一组共同的属性来控制它们的外观。

fill 属性指定几何图形是否被填充 outline 属性指定几何图形是否被勾画。 材质

目前,实体形状和体积支持颜色、图像、棋盘格、条纹和网格材质。对于更复杂的材质,我们需要自己创建一个 MaterialProperty 实例。

MaterialProperty,它有以下几个子类:

ColorMaterialProperty 颜色 ImageMaterialProperty 贴图 CheckerboardMaterialProperty 棋盘 StripeMaterialProperty 条纹 GridMaterialProperty 网格 PolylineGlowMaterialProperty 泛光折线 PolylineOutlineMaterialProperty 带边界折线

image.png

image.png

更多介绍∶ www.cnblogs.com/fuckgiser/p… www.jianshu.com/p/f8fee8643…

// 构造时赋材质 var entity = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(-103.0, 40.0), ellipse : { semiMinorAxis : 250000.0, semiMajorAxis : 400000.0, material : Cesium.Color.BLUE.withAlpha(0.5) } }); viewer.zoomTo(viewer.entities); var ellipse = entity.ellipse; // 下面例子使用的实例 复制代码 颜色 // 构造后赋材质 ellipse.material = Cesium.Color.BLUE.withAlpha(0.5); 复制代码

image.png

图片

图片纹理功能比较丰富,主要有下面属性:

image 值可以是URL,Canvas,或者Video。 repeat 值为一个二位数,分别表示x,y方向的重复次数,例如new Cartesian2(2.0, 1.0)表示x方向重复2次,y方向重复1次。 color 设置颜色之后,会在图片上覆盖一层设置的颜色。 transparent 是否透明,纹理为png图片的时候可以设置。 // 完整的这么写 ellipse.material = new Cesium.ImageMaterialProperty({ image:'../images/cats.jpg', color: Cesium.Color.BLUE, repeat : new Cesium.Cartesian2(4, 4) }); // 也可以简单的写成 ellipse.material = '/docs/tutorials/creating-entities/images/cats.jpg'; 复制代码

image.png

image.png

注意:在http网址中调用https网址图片,可能会调用失败。

棋盘 evenColor 默认白色,棋盘的第一个颜色 oddColor 默认黑色,第二个颜色 repeat 重复次数 ellipse.material = new Cesium.CheckerboardMaterialProperty({ evenColor : Cesium.Color.WHITE, oddColor : Cesium.Color.BLACK, repeat : new Cesium.Cartesian2(6, 4) }); 复制代码

image.png

条纹 evenColor 默认白色,第一个颜色 oddColor 默认黑色,第二个颜色 repeat 条纹重复次数 offset 偏移量 orientation 水平或者垂直,默认水平 ellipse.material = new Cesium.StripeMaterialProperty({ evenColor: Cesium.Color.WHITE, oddColor: Cesium.Color.BLACK, repeat: 32, offset: 20, orientation: Cesium.StripeOrientation.VERTICAL // 垂直 }); 复制代码

image.png

网格 color 网格颜色 cellAlpha 单元格透明度 lineCount 行列个数 lineThickness 线粗细 lineOffset 线偏移 ellipse.material = new Cesium.GridMaterialProperty({ color : Cesium.Color.YELLOW, cellAlpha : 0.2, lineCount : new Cesium.Cartesian2(8, 8), lineThickness : new Cesium.Cartesian2(2.0, 2.0) }); 复制代码

image.png

折线

Polylines 是一种特殊情况,因为它们 没有填充或轮廓属性。除了颜色之外,他们依赖专门的材料来制作任何东西。由于这些特殊材料,polylines不同宽度和轮廓宽度的材料适用于所有系统。

var entity = viewer.entities.add({ polyline : { positions : Cesium.Cartesian3.fromDegreesArray([-77, 35, -77.1, 35]), width : 5, material : Cesium.Color.RED } }); viewer.zoomTo(viewer.entities); var polyline = entity.polyline // 下面例子使用的实例 复制代码

创建实体 polylineMaterialColor

折线轮廓 color 线的颜色 outlineWidth 线纹理宽度 outlineColor 线纹理颜色 polyline.material = new Cesium.PolylineOutlineMaterialProperty({ color : Cesium.Color.ORANGE, outlineWidth : 3, outlineColor : Cesium.Color.BLACK }); 复制代码

创建实体 polylineMaterialOutline

折线发光 color 发光的颜色(中心颜色为白色) glowPower 发光的长度,值为 线宽 的百分比(0~1.0) polyline.material = new Cesium.PolylineGlowMaterialProperty({ glowPower : 0.2, color : Cesium.Color.BLUE }); 复制代码

创建实体 polylineMaterialGlow

轮廓

outline 依赖于outlineColor 和outlineWidth属性。outlineWidth仅适用于非 Windows 系统,例如 Android、iOS、Linux 和 OS X。在 Windows 系统上,轮廓的宽度始终为 1。这是由于 WebGL 在 Windows 上的实现方式的限制。

ellipse.fill = false; ellipse.outline = true; ellipse.outlineColor = Cesium.Color.YELLOW; ellipse.outlineWidth = 2.0; 复制代码

image.png

高度 height 和 挤压 extrudedHeight

平面形状包括corridor、ellipse、polygon和 rectangles 可以放置在高处或挤压成一个立方体。在这两种情况下,仍符合 WGS84 椭球的曲率。

在相应的图形对象上设置 height 属性(距离地面的高度),以米为单位。 // 将多边形提升到地球上方 250,000 米 wyoming.polygon.height = 250000; 复制代码

创建实体高度

要将平面图形转为立方体,请设置 extrudedHeight 属性(拉伸后的面距离地面的拉伸高度)。 立方体将在height 和extrudedHeight之间创建(实际物体的高是 extrudedHeight - height)。 如果height 是undefined,则体积从 0 开始。

创建一个从 200,000 米开始并延伸到 250,000 米的立方体。

wyoming.polygon.height = 200000; // 顶面高度 wyoming.polygon.extrudedHeight = 250000; // 离地面高度 复制代码

image.png

管理实体

EntityCollection 是用于管理和监视一组实体的关联数组。 viewer.entities 是一个 EntityCollection。 EntityCollection 包括诸如 add, remove,removeAll 等用于管理实体的方法。

新增

有时我们需要更新我们之前创建的实体。所有实体实例都有一个唯一的 ,可用于从集合中检索实体。我们可以指定一个 ID,否则会自动生成一个。

var entity = new Entity({ id : 'uniqueId' }); viewer.entities.add(entity); // 简写 viewer.entities.add({ id : 'uniqueId' }); 复制代码

要获取实体或创建一个新实体(如果它不存在),请使用 getOrCreateEntity。

var entity = viewer.entities.getOrCreateEntity('uniqueId'); 复制代码

手动创建一个新实体并使用add将其添加到集合中。如果集合中已存在具有相同id的实体,将引发报错。

var entity = new Entity({ id : 'uniqueId' }); viewer.entities.add(entity); 复制代码 查询/获取

使用getById检索实体。如果不存在具有所提供 ID 的实体,则返回undefined。

var entity = viewer.entities.getById('uniqueId'); 复制代码 删除 //方法一,先查后删 var entity = viewer.entities.getById('uniqueId'); viewer.entities.remove(entity) //方法二,直接删除 viewer.entities.removeById('uniqueId') //方法三,删除所有 viewer.entities.removeAll() 复制代码 变化

EntityCollection的强大之处在于:使用 collectionChanged 事件。这会在集合中添加、删除或更新实体时通知侦听器。

function onChanged(collection, added, removed, changed){ var msg = 'Added ids'; for(var i = 0; i < added.length; i++) { msg += '\n' + added[i].id; } console.log(msg); } viewer.entities.collectionChanged.addEventListener(onChanged); 复制代码

运行示例时,您应该在控制台中看到大约 65 条消息,每次调用viewer.entities.add 时都会显示一条 消息。

当一次更新大量实体时,将更改排队并在最后发送一个大事件会更高效。通过这种方式,cesium 可以一次性处理所需的更改。

在 viewer.entities.add 前使用 viewer.entities.suspendEvents 暂停触发 collectionChanged 事件,添加结束后使用 viewer.entities.resumeEvents 发送一个大事件。

我们现在得到一个包含所有 65 个实体的事件。这些调用是引用计数的,因此可以嵌套多个挂起和恢复调用。

点击选中实体

挑选(单击以选择对象)是我们需要与 Primitive API 进行简短交互的领域之一。

scene.pick 返回所提供窗口坐标处的 最顶层 实体 scene.drillPick 返回在提供的窗口坐标处的实体列表。实体按照视觉顺序从前到后进行排序。 // 返回所提供窗口坐标处的 最顶层实体 function pickEntity(viewer, windowPosition) { var picked = viewer.scene.pick(windowPosition); // 返回所提供窗口坐标处的 最顶层实体 if (defined(picked)) { var id = Cesium.defaultValue(picked.id, picked.primitive.id); // 如果不是undefined则返回第一个参数,否则返回第二个参数。用于设置参数的默认值。 if (id instanceof Cesium.Entity) { return id; } } return undefined; }; // 返回所提供窗口坐标处的 实体列表 function drillPickEntities(viewer, windowPosition) { var i, entity, picked; var pickedPrimitives = viewer.scene.drillPick(windowPosition); // 返回在提供的窗口坐标处的实体列表 var length = pickedPrimitives.length; var result = []; var hash = {}; for (i = 0; i < length; i++) { picked = pickedPrimitives[i]; entity = Cesium.defaultValue(picked.id, picked.primitive.id); if (entity instanceof Cesium.Entity && !Cesium.defined(hash[entity.id])) { result.push(entity); hash[entity.id] = true; } } return result; }; 复制代码 查看器中的实体功能 选择 SelectionIndicator 和 描述 description

单击查看器中的实体将 SelectionIndicator (当前选中实体) 在实体位置显示(绿色小方框),并调出 InfoBox 小部件以提供更多信息。我们可以设置一个名称,它决定了 InfoBox的标题。我们还可以提供 HTML 作为 Entity.description 属性。

InfoBox中显示的所有 HTML都是沙盒化的。要在描述中运行 JavaScript 或浏览器插件,请通过 viewer.infoBox.frame属性访问用于沙箱的 iframe 。有关控制 iframe 沙箱的更多信息,请参阅此文章。

wyoming.name = 'wyoming'; // 标题 // 描述内容 wyoming.description = '\ \

\ Wyoming is a state in the mountain region of the Western \ United States.\

\

\ Wyoming is the 10th most extensive, but the least populous \ and the second least densely populated of the 50 United \ States. The western two thirds of the state is covered mostly \ with the mountain ranges and rangelands in the foothills of \ the eastern Rocky Mountains, while the eastern third of the \ state is high elevation prairie known as the High Plains. \ Cheyenne is the capital and the most populous city in Wyoming, \ with a population estimate of 63,624 in 2017.\

\

\ Source: \ Wikpedia\

'; 复制代码

image.png

批量加载实体 czml

CZML是一种JSON格式的字符串,用于描述与时间有关的动画场景,CZML包含点、线、地标、模型、和其他的一些图形元素,并指明了这些元素如何随时间而变化。

let czml = [ { "id" : "document", "name" : "box", "version" : "1.0" }, { "id" : "shape2", "name" : "Red box with black outline", "position" : { "cartographicDegrees" : [-107.0, 40.0, 300000.0] }, "box" : { "dimensions" : { "cartesian": [400000.0, 300000.0, 500000.0] }, "material" : { "solidColor" : { "color" : { "rgba" : [255, 0, 0, 128] } } }, "outline" : true, "outlineColor" : { "rgba" : [0, 0, 0, 255] } } } ]; let viewer = new Cesium.Viewer('cesiumContainer'); let dataSourcePromise = Cesium.CzmlDataSource.load(czml); // 加载czml viewer.dataSources.add(dataSourcePromise); viewer.zoomTo(dataSourcePromise); 复制代码

image.png

json let geojson = { "type": "FeatureCollection", "features": [ { "type": "Feature", "id": "qsd.1", "geometry": { "type": "Point", "coordinates": [ 113.1187, 22.0882 ] }, "geometry_name": "the_geom", "properties": { "id": "fid--8b96061_17ae14d52ca_-8000", "MC": "¹ÛÒôɽȡˮµã", "OBJECTID": "1152" }, "bbox": [ 113.1187, 22.0882, 113.1187, 22.0882 ] }, ... ] } let viewer = new Cesium.Viewer('cesiumContainer'); let promise = Cesium.GeoJsonDataSource.load(geojson) // 加载geojson promise.then(function (dataSource) { viewer.dataSources.add(dataSource) //向地图加载要素 let entities = dataSource.entities.values // 获取所有实体 // 给实体设置样式 for (let i = 0; i < entities.length; i++) { let entity = entities[i] entity.billboard.width = 24 entity.billboard.height = 24 entity.billboard.image = '../../data/img/qsd.png' entity.billboard.scale = 1 entity.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND entity.label = { // text: entity.id, text: entity.properties.OBJECTID, font:'12px sans-serif', fillColor: Cesium.Color.BLACK, outlineColor: Cesium.Color.WHITE, outlineWidth: 6, style: Cesium.LabelStyle.FILL_AND_OUTLINE, verticalOrigin: Cesium.VerticalOrigin.CENTER,//设置此标签的垂直原点,该垂直原点确定标签是在其锚位置的上方,下方还是中心 horizontalOrigin: Cesium.HorizontalOrigin.CENTER,//设置此标签的垂直原点,该垂直原点确定标签是在其锚位置的上方,下方还是中心 heightReference:Cesium.CLAMP_TO_GROUND } } viewer.flyTo(dataSource) // 聚焦 }).otherwise(function (error) { console.log("请求失败", error) }) 复制代码

image.png

Entity 聚合 const getTextColor = function(colors){ return Cesium.Color.fromCssColorString(colors) } const loadWhiteModel = function () { let promise = Cesium.GeoJsonDataSource.load('../../data/json/qsd.json') // 加载数据 promise.then(function (dataSource) { /* 聚合 */ viewer.dataSources.add(dataSource).then(function (source) { const pixelRange = 30 const minClusterSize = 10 source.clustering.enabled = true; // 是否聚合 source.clustering.pixelRange = pixelRange; // 聚合范围(单位px) source.clustering.minimumClusterSize = minClusterSize; // 最小屏幕聚合对象数值(小于等于该数值,不聚合) source.clustering.clusterBillboards = true; // 是否将实体的广告牌聚类 source.clustering.clusterLabels = true; // 是否将实体的标签聚类 source.clustering.clusterPoints = true; // 是否将实体的点聚类 source.clustering.clusterEvent.addEventListener(function (entities, cluster) { // 判断实体数量设置颜色 let color let num = entities.length; switch (true) { case num >= minClusterSize && num 200 && num 500: color = '#ff0000'; break; // 绿 } cluster.point.show = true; cluster.point.pixelSize = pixelRange cluster.point.color = getTextColor(color) cluster.label.show = true; cluster.label.font = '12px sans-serif' cluster.label.fillColor = Cesium.Color.WHITE cluster.label.outlineColor = Cesium.Color.BLACK // cluster.label.outlineWidth = 4 cluster.label.verticalOrigin = Cesium.VerticalOrigin.CENTER cluster.label.style = Cesium.LabelStyle.FILL_AND_OUTLINE cluster.label.horizontalOrigin = Cesium.HorizontalOrigin.CENTER // cluster.label.pixelOffset = new Cesium.Cartesian2(0, 20) cluster.label.eyeOffset = new Cesium.Cartesian3(0, 0, -100) // 设为负值则在更上层,不会被盖住 cluster.label.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND }); }); viewer.flyTo(dataSource) /* 给实体设置样式 */ let entities = dataSource.entities.values // 获取所有实体 for (let i = 0; i < entities.length; i++) { let entity = entities[i] entity.billboard.width = 24 entity.billboard.height = 24 entity.billboard.image = '../../data/img/qsd.png' entity.billboard.scale = 1 entity.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND } }).otherwise(function (error) { console.log("error", error) Vue.prototype.$message({ type: "error", showClose: true, message: '图层请求失败,请联系管理员' }) }) } loadWhiteModel() 复制代码

image.png

按需加载实体 加载json数据,创建实体,控制加载实体的瓦片层级 获取当前被渲染的瓦片构成的集合,通过求并集拼成一个大的矩形(也许称为范围可能更合适,但是毕竟使用的是矩形方法) 根据矩形方法判断点是否在矩形中,如果在,则加载当前实体,否则删除当前实体 let entities = [] // 加载数据 function loadWhiteModel () { entities = [] let promise = Cesium.GeoJsonDataSource.load('../../data/json/qsd.json',{ clampToGround : true }) // 加载数据 promise.then(function (dataSource) { viewer.dataSources.add(dataSource) // 向地图加载要素 entities = dataSource.entities.values // 获取所有实体 // 获取所有实体,给实体设置样式,同上 批量加载实体-json viewer.flyTo(dataSource) }).otherwise(function (error) { console.log("error", error) Vue.prototype.$message({ type: "error", showClose: true, message: '图层请求失败,请联系管理员' }) }) } // 按需加载 function onDemandLoad (){ // 获取当前正在渲染的瓦片集合 const tilesToRender = viewer.scene.globe._surface._tilesToRender /** * 添加相机移动结束事件,也就是鼠标移动结束事件 * 由于相机自身有惯性,所以提前关闭惯性会有更好的体验 * 但是这本身并不影响该功能 * */ viewer.camera.moveEnd.addEventListener(()=>{ // 当前正在渲染的瓦片求并集为一个大的 rectangle let renderRectangle = new Cesium.Rectangle() if( tilesToRender.length > 0 ) { /* 获取当前被渲染的瓦片构成的集合,通过求并集拼成一个大的矩形 */ // 初始化总的渲染的矩形瓦片 Cesium.Rectangle.clone(tilesToRender[0].rectangle, renderRectangle) let num = 0 // 符合条件的瓦片数量 tilesToRender.forEach(item => { /** * 获取当前层级大于等于12级的瓦片,该处可自定义,具体层级可根据加载的实体多少决定 * 一般情况下由于相机视角的不同,我们能看见的瓦片数量也不同,所以尽量考虑瓦片数量 * 最多的情况下每块瓦片上的显示数量 */ if( item.level >= 12 ) { // 用来判断当前是否有符合条件的瓦片正在渲染 num += 1 // 所有大于12级的瓦片求交集 Cesium.Rectangle.union(item.rectangle, renderRectangle, renderRectangle) } }) if( num > 0 ){ /* 根据矩形方法判断点是否在矩形中,如果在,则加载当前实体,否则删除当前实体*/ for( let i = 0; i < entities.length; i++ ) { // 将度转为弧度 // let cartographic = Cesium.Cartographic.fromDegrees(labelArr[i][0], labelArr[i][1]) // 笛卡尔转弧度 let cartographic = Cesium.Cartographic.fromCartesian(entities[i].position._value); // 判断点是否在矩形内 if(Cesium.Rectangle.contains(renderRectangle, cartographic)){ // 点在矩形内,判断当前实体是否已经被加载,有则跳过,无则加载 if(viewer.entities.contains(entities[i])) continue viewer.entities.add(entities[i]) } else { // 不点在矩形内,则判断是否被加载,有则删除 if(viewer.entities.contains(entities[i])){ viewer.entities.remove(entities[i]) } } } } else{ for( let i = 0; i < entities.length; i++ ){ /** * 当前可视范围内没有符合条件的瓦片加载,删除掉瓦片内的要素 * 不能使用removeAll,我们只需要管理我们自己加载的部分即可 */ if(viewer.entities.contains(entities[i])){ viewer.entities.remove(entities[i]) } } } } }) } loadWhiteModel() onDemandLoad() 复制代码

image.png



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3